﻿namespace DotRas.Design
{
    using DotRas;
    using pptpclient.Properties;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    using System.Security.Permissions;
    using System.Threading;

    [DebuggerDisplay("Count = {Count}"), PermissionSet(SecurityAction.Demand, Name="FullTrust")]
    public abstract class RasCollection<TObject> : MarshalByRefObject, ICollection<TObject>, IEnumerable<TObject>, IEnumerable where TObject: class
    {
        private bool _initializing;
        private List<TObject> _items;
        private readonly object _syncRoot;

        protected RasCollection()
        {
            this._syncRoot = new object();
            this._items = new List<TObject>();
        }

        public void Add(TObject item)
        {
            if (item == null)
            {
                DotRas.ThrowHelper.ThrowArgumentNullException("item");
            }
            this.InsertItem(this._items.Count, item);
        }

        internal void BeginLock()
        {
            Monitor.Enter(this._syncRoot);
        }

        public void Clear()
        {
            this.ClearItems();
        }

        protected virtual void ClearItems()
        {
            this._items.Clear();
        }

        public bool Contains(TObject item)
        {
            if (item == null)
            {
                DotRas.ThrowHelper.ThrowArgumentNullException("item");
            }
            return this._items.Contains(item);
        }

        public void CopyTo(TObject[] array, int arrayIndex)
        {
            if (array == null)
            {
                DotRas.ThrowHelper.ThrowArgumentNullException("array");
            }
            if (arrayIndex < 0)
            {
                DotRas.ThrowHelper.ThrowArgumentOutOfRangeException("arrayIndex", arrayIndex, Resources.Argument_ValueCannotBeLessThanZero);
            }
            this._items.CopyTo(array, arrayIndex);
        }

        internal void EndLock()
        {
            Monitor.Exit(this._syncRoot);
        }

        public IEnumerator<TObject> GetEnumerator()
        {
            return new RasCollectionEnumerator<TObject>((RasCollection<TObject>) this);
        }

        public int IndexOf(TObject item)
        {
            if (item == null)
            {
                DotRas.ThrowHelper.ThrowArgumentNullException("item");
            }
            return this._items.IndexOf(item);
        }

        protected virtual void InsertItem(int index, TObject item)
        {
            this._items.Insert(index, item);
        }

        public bool Remove(TObject item)
        {
            if (item == null)
            {
                DotRas.ThrowHelper.ThrowArgumentNullException("item");
            }
            bool flag = false;
            int index = this.IndexOf(item);
            if (index != -1)
            {
                this.RemoveAt(index);
                flag = true;
            }
            return flag;
        }

        public void RemoveAt(int index)
        {
            this.RemoveItem(index);
        }

        protected virtual void RemoveItem(int index)
        {
            this._items.RemoveAt(index);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new RasCollectionEnumerator<TObject>((RasCollection<TObject>) this);
        }

        public int Count
        {
            get
            {
                return this._items.Count;
            }
        }

        protected bool IsInitializing
        {
            get
            {
                return this._initializing;
            }
            set
            {
                this._initializing = value;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public TObject this[int index]
        {
            get
            {
                return this._items[index];
            }
        }

        private class RasCollectionEnumerator : IEnumerator<TObject>, IDisposable, IEnumerator
        {
            private RasCollection<TObject> _c;
            private TObject _current;
            private int _index;

            public RasCollectionEnumerator(RasCollection<TObject> c)
            {
                this._index = -1;
                if (c == null)
                {
                    DotRas.ThrowHelper.ThrowArgumentNullException("c");
                }
                this._c = c;
                this._c.BeginLock();
            }

            public void Dispose()
            {
                this.Dispose(true);
                GC.SuppressFinalize(this);
            }

            private void Dispose(bool disposing)
            {
                if (disposing)
                {
                    this._c.EndLock();
                    this._index = -1;
                    this._current = default(TObject);
                }
            }

            ~RasCollectionEnumerator()
            {
                this.Dispose(false);
            }

            public bool MoveNext()
            {
                this._index++;
                if (this._index == this._c.Count)
                {
                    this._index = -1;
                    this._current = default(TObject);
                    return false;
                }
                this._current = this._c[this._index];
                return true;
            }

            public void Reset()
            {
                this._index = -1;
                this._current = default(TObject);
            }

            public TObject Current
            {
                get
                {
                    return this._current;
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    return this._current;
                }
            }
        }
    }
}

